"""
认证服务
"""

import jwt
import hashlib
import time
from datetime import datetime, timedelta
from typing import Optional, Dict, Any
from fastapi import HTTPException, Depends, status
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials

from config import get_settings

settings = get_settings()
security = HTTPBearer()

# 存储刷新令牌（生产环境应使用Redis）
REFRESH_TOKENS: Dict[str, Dict[str, Any]] = {}

class AuthService:
    """认证服务类"""
    
    def __init__(self):
        self.secret_key = settings.secret_key
        self.algorithm = settings.algorithm
        self.access_token_expire_minutes = settings.access_token_expire_minutes
        self.refresh_token_expire_days = settings.refresh_token_expire_days
    
    def create_access_token(self, data: dict, expires_delta: Optional[timedelta] = None) -> str:
        """创建访问令牌"""
        to_encode = data.copy()
        if expires_delta:
            expire = datetime.utcnow() + expires_delta
        else:
            expire = datetime.utcnow() + timedelta(minutes=self.access_token_expire_minutes)
        
        to_encode.update({"exp": expire})
        encoded_jwt = jwt.encode(to_encode, self.secret_key, algorithm=self.algorithm)
        return encoded_jwt
    
    def create_refresh_token(self, user_id: int) -> str:
        """创建刷新令牌"""
        token = hashlib.sha256(f"{user_id}_{time.time()}".encode()).hexdigest()
        REFRESH_TOKENS[token] = {
            "user_id": user_id,
            "created_at": time.time()
        }
        return token
    
    def verify_token(self, token: str) -> Dict[str, Any]:
        """验证访问令牌"""
        try:
            payload = jwt.decode(token, self.secret_key, algorithms=[self.algorithm])
            return payload
        except jwt.ExpiredSignatureError:
            raise HTTPException(
                status_code=status.HTTP_401_UNAUTHORIZED,
                detail={
                    "code": "TOKEN_EXPIRED",
                    "type": "authentication_error", 
                    "message": "访问令牌已过期",
                    "action": "refresh_token"
                },
                headers={"WWW-Authenticate": "Bearer"},
            )
        except jwt.InvalidTokenError:
            raise HTTPException(
                status_code=status.HTTP_401_UNAUTHORIZED,
                detail={
                    "code": "TOKEN_INVALID",
                    "type": "authentication_error",
                    "message": "无效的认证令牌", 
                    "action": "relogin"
                },
                headers={"WWW-Authenticate": "Bearer"},
            )
        except jwt.PyJWTError:
            raise HTTPException(
                status_code=status.HTTP_401_UNAUTHORIZED,
                detail={
                    "code": "TOKEN_INVALID",
                    "type": "authentication_error",
                    "message": "认证令牌解析失败",
                    "action": "relogin"
                },
                headers={"WWW-Authenticate": "Bearer"},
            )
    
    def verify_refresh_token(self, refresh_token: str) -> Optional[int]:
        """验证刷新令牌"""
        token_info = REFRESH_TOKENS.get(refresh_token)
        if not token_info:
            return None
        
        # 检查令牌是否过期
        if time.time() - token_info["created_at"] > self.refresh_token_expire_days * 24 * 3600:
            del REFRESH_TOKENS[refresh_token]
            return None
        
        return token_info["user_id"]
    
    def revoke_refresh_token(self, refresh_token: str) -> bool:
        """撤销刷新令牌"""
        if refresh_token in REFRESH_TOKENS:
            del REFRESH_TOKENS[refresh_token]
            return True
        return False

def get_current_user(credentials: HTTPAuthorizationCredentials = Depends(security)) -> dict:
    """获取当前用户"""
    auth_service = AuthService()
    payload = auth_service.verify_token(credentials.credentials)
    
    username = payload.get("sub")
    user_id = payload.get("user_id")
    
    if username is None or user_id is None:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail={
                "code": "TOKEN_INVALID",
                "type": "authentication_error",
                "message": "令牌中缺少必要的用户信息",
                "action": "relogin"
            },
            headers={"WWW-Authenticate": "Bearer"},
        )
    
    return {
        "id": user_id,
        "username": username
    }